package org.qdog.pk.pkscrape.test;

import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;

import java.util.ArrayList;
import java.util.List;

/**
 * @since 08/2011
 */
public class DependsOnBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

  private List<String> beanIdsInLoadOrder = new ArrayList<String>(0);

  /**
   * a list of bean ids in the order that they must be loaded.
   *
   * @param beanIdsInLoadOrder
   */
  public void setBeanIdsInLoadOrder(List<String> beanIdsInLoadOrder) {
    this.beanIdsInLoadOrder = beanIdsInLoadOrder;
  }

  /**
   * takes the bean ids specified in the beanIdsInLoadOrder and ensures that that are loaded in the
   * correct sequence by adding depends-on to to the BeanDefinition.
   *
   * NOTE: This doesn't work on parent beans. You must specify the actual bean.
   *
   * @param beanFactory
   * @throws BeansException
   */
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    if (beanIdsInLoadOrder != null) {
      //The existing implementation class for ConfigurableListableBeanFactory. It happens to implement BeanDefinitionRegistry as well.
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      for (int i=1; i<beanIdsInLoadOrder.size();i++) {
        String beanName = beanIdsInLoadOrder.get(i);
        BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
        String[] oldDependsOn = bd.getDependsOn();

        List<String> dependsOnArray = new ArrayList<String>(5);
        dependsOnArray.add(beanIdsInLoadOrder.get(i-1));
        for (int j=0; j<ArrayUtils.getLength(oldDependsOn); j++) {
          dependsOnArray.add(oldDependsOn[j]);
        }

        bd.setDependsOn(dependsOnArray.toArray(new String[dependsOnArray.size()]));

        BeanDefinitionHolder bdh = new BeanDefinitionHolder(bd,beanName);
        BeanDefinitionReaderUtils.registerBeanDefinition(bdh,registry);
      }
    }
  }
}
